package com.sky.his.api.mis.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import com.sky.his.api.common.MinioUtil;
import com.sky.his.api.common.OcrUtil;
import com.sky.his.api.common.PageUtils;
import com.sky.his.api.db.dao.AppointmentDao;
import com.sky.his.api.db.dao.CheckupReportDao;
import com.sky.his.api.db.dao.CheckupResultDao;
import com.sky.his.api.db.pojo.CheckupResultEntity;
import com.sky.his.api.exception.HisException;
import com.sky.his.api.mis.service.CheckupReportService;
import com.sky.his.api.mis.service.CheckupService;
import com.sky.his.api.report.CheckupReportUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.data.mongodb.core.aggregation.VariableOperators;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.awt.*;
import java.io.*;
import java.util.*;
import java.util.List;

/**
 * @Author: WangJiYou
 * @Date: 2024/12/17/18:04
 * @Description:
 */
@Service
@Slf4j
public class CheckupReportServiceImpl implements CheckupReportService {

    @Resource
    private CheckupReportDao checkupReportDao;

    @Resource
    private CheckupResultDao checkupResultDao;

    @Resource
    private AppointmentDao appointmentDao;

    @Resource
    private MinioUtil minioUtil;

    @Resource
    private CheckupReportUtil checkupReportUtil;

    @Resource
    private OcrUtil ocrUtil;


    @Override
    public PageUtils searchByPage(Map param) {
        // 初始化返回结果列表
        List<HashMap> list = new ArrayList<>();

        // 查询符合条件的记录总数
        long count = checkupReportDao.searchCount(param);

        // 如果查询到的数据条数大于0，进行分页查询
        if (count > 0) {
            list = checkupReportDao.searchByPage(param);
        }

        // 获取分页参数
        int page = MapUtil.getInt(param, "page");
        int length = MapUtil.getInt(param, "length");

        // 构造分页工具类对象并返回
        PageUtils pageUtils = new PageUtils(list, count, page, length);
        return pageUtils;
    }

    @SneakyThrows
    @Override
    @Transactional
    public boolean createReport(Integer id) {
        HashMap result = checkupReportDao.searchById(id);
        if (result == null || result.size() == 0) {
            throw new HisException("不存在体检报告记录");
        }
        Integer appointmentId = MapUtil.getInt(result, "appointmentId");
        String resultId = MapUtil.getStr(result, "resultId");
        Integer status = MapUtil.getInt(result, "status");
        DateTime date = DateUtil.parseDate(MapUtil.getStr(result, "date"));
        DateTime today = new DateTime(DateUtil.today());
        if (today.offsetNew(DateField.DAY_OF_MONTH, -10).isBefore(date)) {
            throw new HisException("无法生成10天内的体检报告");
        }
        if (status != 1) {
            log.debug("主键为" + id + "的体检报告已经生成，当前任务自动结束");
            return true;
        }
        HashMap map = appointmentDao.searchDataForReport(appointmentId);

        CheckupResultEntity entity = checkupResultDao.searchById(resultId);
        List<Map> checkup = entity.getCheckup();
        map.put("checkup", checkup);
        map.put("result", entity.getResult());

        HashSet set = new HashSet();

        checkup.forEach(one -> {
            String place = MapUtil.getStr(one, "place");
            set.add(place);
        });
        List<String> placeList = entity.getPlace();
        if (placeList.size() < set.size()) {
            log.debug("主键为" + id + "的体检存在没有录入的体检结果");
            return false;
        }
        XWPFDocument report = checkupReportUtil.createReport(map);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        report.write(out);
        out.flush();
        InputStream in = new ByteArrayInputStream(out.toByteArray());
        String filePath = "/report/checkup/" + resultId + ".docx";
        minioUtil.uploadByWord(filePath, in);

        checkupReportDao.update(new HashMap() {
            {
                put("status", 2);
                put("filePath", filePath);
                put("id", id);
            }
        });
        return true;
    }

    @Override
    public HashMap identifyWaybill(String imagBase64) {
        try {
            HashMap map = ocrUtil.identifyWaybill(imagBase64);
            return map;
        } catch (Exception e) {
            log.error("OCR运单识别异常", e);
            throw new HisException("OCR识别异常");
        }
    }

    @Override
    @Transactional
    public boolean addWayBill(Map param) {
        int rows = checkupReportDao.update(param);
        return rows == 1;
    }

    @Override
    @Transactional
    public XSSFWorkbook importWayBill(MultipartFile file) {
        ArrayList list = new ArrayList<>();
        try {
            InputStream in = file.getInputStream();
            XSSFWorkbook workbook = new XSSFWorkbook(in);
            XSSFSheet sheet = workbook.getSheetAt(0);
            for (int i = 0; i < sheet.getLastRowNum(); i++) {
                XSSFRow row = sheet.getRow(i);  // 修正了行的引用
                String uuid = row.getCell(1).getStringCellValue();  // 修正了方法名
                String recName = row.getCell(2).getStringCellValue();  // 修正了方法名
                String recTel = row.getCell(3).getStringCellValue();  // 修正了方法名
                String waybillCode = row.getCell(4).getStringCellValue();  // 修正了方法名

                // 查询体检人信息
                HashMap<String, Object> map = appointmentDao.searchDataForWaybill(uuid);  // 修正了方法调用
                if (map == null || map.size() == 0) {  // 修正了判断条件
                    // 记录 uuid 有误的运单信息
                    list.add(new HashMap<String, Object>() {{
                        put("uuid", uuid);
                        put("recName", recName);
                        put("recTel", recTel);
                        put("waybillCode", waybillCode);  // 修正了键名
                        put("result", "体检编号错误");  // 修正了键名和值
                    }});
                    continue;
                }
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        if (list.size() == 0) {  // 修改了条件判断
            return null;
        }

        XSSFWorkbook workbook = new XSSFWorkbook();  // 创建 XSSFWorkbook 对象

        XSSFCellStyle style = workbook.createCellStyle();  // 创建单元格样式

        style.setBorderBottom(BorderStyle.MEDIUM);
        style.setBorderLeft(BorderStyle.MEDIUM);
        style.setBorderTop(BorderStyle.MEDIUM);
        style.setBorderRight(BorderStyle.MEDIUM);

        XSSFFont font = workbook.createFont();
        font.setFontName("微软雅黑");  // 修正了字体名称中的引号问题
        font.setFontHeightInPoints((short) 10);  // 设置字体大小为 10 号
        style.setFont(font);  // 应用字体到样式

        // 设置单元格数据格式为文本类型
        XSSFDataFormat dataFormat = workbook.createDataFormat();
        style.setDataFormat(dataFormat.getFormat("@"));  // 设置文本格式

        XSSFSheet sheet = workbook.createSheet("导入失败的运单");

        sheet.setColumnWidth(0, 3000);
        sheet.setColumnWidth(1, 7000);
        sheet.setColumnWidth(2, 5000);
        sheet.setColumnWidth(3, 5000);
        sheet.setColumnWidth(4, 7000);
        sheet.setColumnWidth(5, 7000);

        XSSFRow row = sheet.createRow(0);

        XSSFCellStyle headerStyle = workbook.createCellStyle();
        headerStyle.cloneStyleFrom(style);  // 克隆之前的样式

        XSSFColor color = new XSSFColor(new Color(255, 255, 0), new DefaultIndexedColorMap());  // 修正颜色创建方式
        headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);  // 填充背景色
        headerStyle.setFillForegroundColor(color);  // 设置填充颜色

        XSSFCell cell = row.createCell(0);
        cell.setCellStyle(headerStyle);
        cell.setCellValue("序号");

        cell = row.createCell(1);
        cell.setCellStyle(headerStyle);
        cell.setCellValue("体检编号");

        cell = row.createCell(2);
        cell.setCellStyle(headerStyle);
        cell.setCellValue("收件人");

        cell = row.createCell(5);
        cell.setCellStyle(headerStyle);
        cell.setCellValue("导入失败原因");


        // 输出表头行下方的行记录
        for (int i = 1; i < list.size(); i++) {  // 修正了循环的初始化和条件
            Map map = (Map) list.get(i - 1);  // 修正了获取 list 中元素的方式

            String waybillCode = MapUtil.getStr(map, "waybillCode");  // 修正了方法名的大小写
            String uuid = MapUtil.getStr(map, "uuid");
            String recName = MapUtil.getStr(map, "recName");
            String recTel = MapUtil.getStr(map, "recTel");
            String result = MapUtil.getStr(map, "result");

            // 创建行对象
            row = sheet.createRow(i);

            // 创建单元格并设置值
            cell = row.createCell(0);
            cell.setCellStyle(style);  // 设置单元格样式
            cell.setCellValue(i);  // 设置序号

            cell = row.createCell(1);
            cell.setCellStyle(style);
            cell.setCellValue(uuid);  // 设置 uuid

            cell = row.createCell(2);
            cell.setCellStyle(style);
            cell.setCellValue(recName);  // 设置收件人姓名

            cell = row.createCell(3);
            cell.setCellStyle(style);
            cell.setCellValue(recTel);  // 设置电话

            cell = row.createCell(4);
            cell.setCellStyle(style);
            cell.setCellValue(waybillCode);  // 设置运单号

            cell = row.createCell(5);
            cell.setCellStyle(style);
            cell.setCellValue(result);  // 设置体检结果
        }
        return workbook;
    }
}
